package com.gpframework.module.manufacture.service.impl;

import cn.hutool.core.convert.Convert;
import cn.hutool.core.lang.TypeReference;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.gpframework.common.enums.YesNoEnum;
import com.gpframework.common.utils.StringUtils;
import com.gpframework.module.manufacture.domain.*;
import com.gpframework.module.manufacture.domain.req.GpProductionFlowUpdate;
import com.gpframework.module.manufacture.service.*;
import com.gpframework.module.module.domain.GpDeliveryNote;
import com.gpframework.module.module.service.IGpDeliveryNoteService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.gpframework.module.manufacture.mapper.GpProductionFlowMapper;
import com.gpframework.module.manufacture.domain.vo.GpProductionFlowVo;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.ArrayList;
import java.util.List;
/**
 * @ClassName GpProductionFlow
 * @Author gpframework
 * @Date 2023-12-13
 * @Version 1.0.0
 * @Description 生产跟踪Service业务层处理
 */
@Service
public class GpProductionFlowServiceImpl extends ServiceImpl<GpProductionFlowMapper, GpProductionFlow> implements IGpProductionFlowService {

    @Autowired
    private IGpDeliveryNoteService iGpDeliveryNoteService;
    @Autowired
    private IGpProductionSchedulingService iGpProductionSchedulingService;
    @Autowired
    private IGpDyeingFactoryDyeingFeeService iGpDyeingFactoryDyeingFeeService;
    @Autowired
    private IGpProductionDetailsService iGpProductionDetailsService;
    @Autowired
    private IGpLossRateService iGpLossRateService;
    @Autowired
    private IGpOutputRateService iGpOutputRateService;

    /**
     * @Description 查询列表返回VO 用于返回给前端的列表接口
     * @Author gpframework
     * @Date 2023-12-13
     * @Param [lqw]
     * @Return List<GpProductionFlowVo>
     */
    @Override
    public List<GpProductionFlowVo> listVo(QueryWrapper<GpProductionFlow> lqw) {
        return this.baseMapper.listVo(lqw);
    }

    /**
     * @Description 通过查询详情VO 用于返回给前端的列详情接口
     * @Author gpframework
     * @Date 2023-12-13
     * @Param [id]
     * @Return GpProductionFlowVo
     */
    @Override
    public GpProductionFlowVo getVoById(Long id) {
        return this.baseMapper.getVo(id);
    }

    /**
     * 生成生产跟踪单
     * @param ids
     * @param createBy
     * @return
     */
    @Override
    @Transactional
    public boolean createProductionFlow(List<Long> ids, String createBy) {
        List<GpProductionFlow> list = new ArrayList<>();
        GpDeliveryNote gpDeliveryNote;
        for (Long id : ids) {
            gpDeliveryNote = iGpDeliveryNoteService.getById(id);
            gpDeliveryNote.setTrackFlag(YesNoEnum.YES.getKey());
            iGpDeliveryNoteService.updateById(gpDeliveryNote);
            GpProductionFlow gpProductionFlow = Convert.convert(new TypeReference<GpProductionFlow>() {}, gpDeliveryNote);
            if (StringUtils.isNotBlank(createBy)) {
                gpProductionFlow.setCreateBy(createBy);
            }
            this.init(gpProductionFlow, gpDeliveryNote);
            gpProductionFlow.setRemarks(null);
            list.add(gpProductionFlow);
        }
        return this.saveBatch(list);
    }

    @Override
    public boolean edit(List<GpProductionFlowUpdate> list) {
        List<GpProductionFlow> updateList = new ArrayList<>();
        GpDeliveryNote gpDeliveryNote;
        for (GpProductionFlowUpdate gpProductionFlowUpdate : list) {
            GpProductionFlow gpProductionFlow = Convert.convert(new TypeReference<GpProductionFlow>() {}, gpProductionFlowUpdate);
            gpDeliveryNote = iGpDeliveryNoteService.getById(gpProductionFlow.getDeliveryNoteId());
            this.init(gpProductionFlow, gpDeliveryNote);
            this.updateGpProductionFlow(gpProductionFlow);
            updateList.add(gpProductionFlow);
        }
        return this.updateBatchById(updateList);
    }

    private void updateGpProductionFlow(GpProductionFlow gpProductionFlow) {
        GpDeliveryNote gpDeliveryNote = iGpDeliveryNoteService.getById(gpProductionFlow.getDeliveryNoteId());
        GpProductionScheduling gpProductionScheduling = iGpProductionSchedulingService.getById(gpProductionFlow.getProductionSchedulingId());
        GpProductionDetails gpProductionDetails = iGpProductionDetailsService.getById(gpProductionFlow.getProductionDetailsId());

        //更新到货单数据
        gpDeliveryNote.setBatchNo(gpProductionFlow.getBatchNo());
        gpDeliveryNote.setDyeVatNo(gpProductionFlow.getDyeVatNo());
        gpDeliveryNote.setQuantity(gpProductionFlow.getQuantity());
        gpDeliveryNote.setSizeBar(gpProductionFlow.getSizeBar());
        gpDeliveryNote.setSupplierName(gpProductionFlow.getSupplierName());
        gpDeliveryNote.setProductName(gpProductionFlow.getProductName());
        gpDeliveryNote.setColour(gpProductionFlow.getColour());
        gpDeliveryNote.setDyeingFactoryName(gpProductionFlow.getDyeingFactoryName());
        iGpDeliveryNoteService.updateById(gpDeliveryNote);

        //更新排单表数据
        gpProductionScheduling.setDyeVatNo(gpProductionFlow.getDyeVatNo());
        gpProductionScheduling.setQuantity(gpProductionFlow.getQuantity());
        gpProductionScheduling.setSupplierName(gpProductionFlow.getSupplierName());
        gpProductionScheduling.setReturnTime(gpProductionFlow.getSendOutGoodsTime());
        gpProductionScheduling.setWarehousePoint(gpProductionFlow.getWarehousePoint());
        gpProductionScheduling.setProductName(gpProductionFlow.getProductName());
        gpProductionScheduling.setColour(gpProductionFlow.getColour());
        gpProductionScheduling.setDyeingFactoryName(gpProductionFlow.getDyeingFactoryName());
        gpProductionScheduling.setWarehouseEntryWeight(gpProductionFlow.getWarehouseEntryWeight());
        iGpProductionSchedulingService.updateById(gpProductionScheduling);

        //更新取做货明细数据
        gpProductionDetails.setDyeVatNo(gpProductionFlow.getDyeVatNo());
        gpProductionDetails.setQuantity(gpProductionFlow.getQuantity());
        gpProductionDetails.setSupplierName(gpProductionFlow.getSupplierName());
        gpProductionDetails.setProductName(gpProductionFlow.getProductName());
        gpProductionDetails.setColour(gpProductionFlow.getColour());
        gpProductionDetails.setDyeingFactoryName(gpProductionFlow.getDyeingFactoryName());
        gpProductionDetails.setCodingSpecifications(gpProductionFlow.getCodingSpecificationsSufficient());
        gpProductionDetails.setTagSpecifications(gpProductionFlow.getCodingSpecificationsEmpty());
        gpProductionDetails.setDyeVatNo(gpProductionFlow.getDyeVatNo());
        gpProductionDetails.setQuantity(gpProductionFlow.getQuantity());
        gpProductionDetails.setSupplierName(gpProductionFlow.getSupplierName());
        gpProductionDetails.setProductName(gpProductionFlow.getProductName());
        gpProductionDetails.setColour(gpProductionFlow.getColour());
        gpProductionDetails.setDyeingFactoryName(gpProductionFlow.getDyeingFactoryName());
        iGpProductionDetailsService.updateById(gpProductionDetails);


    }

    @Override
    public boolean editOne(GpProductionFlowUpdate gpProductionFlowUpdate) {
        GpProductionFlow gpProductionFlow = Convert.convert(new TypeReference<GpProductionFlow>() {}, gpProductionFlowUpdate);
        GpDeliveryNote gpDeliveryNote = iGpDeliveryNoteService.getById(gpProductionFlow.getDeliveryNoteId());
        this.init(gpProductionFlow, gpDeliveryNote);
        return this.updateById(gpProductionFlow);
    }

    @Override
    public boolean copy(Long id, Integer copyNum) {
        GpProductionFlow gpProductionFlow = this.getById(id);
        if (gpProductionFlow == null) {
            return false;
        }
        for (int i = 0; i < copyNum; i++) {
            gpProductionFlow.setId(null);
            this.save(gpProductionFlow);
        }
        return true;
    }

    private void init(GpProductionFlow gpProductionFlow, GpDeliveryNote gpDeliveryNote) {
        gpProductionFlow.setDeliveryNoteId(gpDeliveryNote.getId());
        GpProductionScheduling gpProductionScheduling = iGpProductionSchedulingService.getById(gpProductionFlow.getProductionSchedulingId());
        if (gpProductionScheduling != null) {
            gpProductionFlow.setWarehousePoint(gpProductionScheduling.getWarehousePoint());
            gpProductionFlow.setWarehouseEntryWeight(gpProductionScheduling.getWarehouseEntryWeight());
        }
        GpProductionDetails gpProductionDetails = iGpProductionDetailsService.getById(gpProductionFlow.getProductionDetailsId());
        if (gpProductionDetails != null) {
            gpProductionFlow.setCodingSpecificationsId(gpProductionDetails.getCodingSpecificationsId());
            gpProductionFlow.setCodingSpecificationsSufficient(gpProductionDetails.getCodingSpecifications());
            gpProductionFlow.setCodingSpecificationsEmpty(gpProductionDetails.getTagSpecifications());
        }
        // 染费单价
        if (gpProductionFlow.getDyeingFeeUnitPrice() == null) {
            // 没传染费价格过来，则从基础表中获取染费价格
            if (StringUtils.isNotBlank(gpProductionFlow.getDyeingFactoryName()) && StringUtils.isNotBlank(gpProductionFlow.getProductName()) && StringUtils.isNotBlank(gpProductionFlow.getColour())) {
                GpDyeingFactoryDyeingFee gpDyeingFactoryDyeingFee = iGpDyeingFactoryDyeingFeeService.getOne(new LambdaQueryWrapper<GpDyeingFactoryDyeingFee>()
                        .eq(GpDyeingFactoryDyeingFee::getDyeingFactoryName, gpProductionFlow.getDyeingFactoryName())
                        .eq(GpDyeingFactoryDyeingFee::getProductName, gpProductionFlow.getProductName())
                        .eq(GpDyeingFactoryDyeingFee::getColour, gpProductionFlow.getColour())
                        .eq(GpDyeingFactoryDyeingFee::getDelStatus, YesNoEnum.NO.getKey())
                        .last("limit 1"));
                if (gpDyeingFactoryDyeingFee != null) {
                    gpProductionFlow.setDyeingFeeUnitPrice(gpDyeingFactoryDyeingFee.getPrice());
                }
            }
        } else {
            // 传了染费价格过来，判断基础表中有无对应数据，没有则新增
            GpDyeingFactoryDyeingFee addDyeingFactoryDyeingFee = new GpDyeingFactoryDyeingFee();
            addDyeingFactoryDyeingFee.setPrice(gpProductionFlow.getDyeingFeeUnitPrice());
            LambdaQueryWrapper<GpDyeingFactoryDyeingFee> lqw = new LambdaQueryWrapper<GpDyeingFactoryDyeingFee>()
                    .eq(GpDyeingFactoryDyeingFee::getDelStatus, YesNoEnum.NO.getKey())
                    .last("limit 1");
            if (StringUtils.isNotBlank(gpProductionFlow.getDyeingFactoryName())) {
                lqw.eq(GpDyeingFactoryDyeingFee::getDyeingFactoryName, gpProductionFlow.getDyeingFactoryName());
                addDyeingFactoryDyeingFee.setDyeingFactoryName(gpProductionFlow.getDyeingFactoryName());
            }
            if (StringUtils.isNotBlank(gpProductionFlow.getProductName())) {
                lqw.eq(GpDyeingFactoryDyeingFee::getProductName, gpProductionFlow.getProductName());
                addDyeingFactoryDyeingFee.setProductName(gpProductionFlow.getProductName());
            }
            if (StringUtils.isNotBlank(gpProductionFlow.getColour())) {
                lqw.eq(GpDyeingFactoryDyeingFee::getColour, gpProductionFlow.getColour());
                addDyeingFactoryDyeingFee.setColour(gpProductionFlow.getColour());
            }
            GpDyeingFactoryDyeingFee gpDyeingFactoryDyeingFee = iGpDyeingFactoryDyeingFeeService.getOne(lqw);
            if (gpDyeingFactoryDyeingFee == null) {
                iGpDyeingFactoryDyeingFeeService.save(addDyeingFactoryDyeingFee);
            } else if (gpProductionFlow.getDyeingFeeUnitPrice().compareTo(gpDyeingFactoryDyeingFee.getPrice()) != 0){
                gpDyeingFactoryDyeingFee.setPrice(gpProductionFlow.getDyeingFeeUnitPrice());
                iGpDyeingFactoryDyeingFeeService.updateById(gpDyeingFactoryDyeingFee);
            }

        }
        // 正常损耗值
        if (StringUtils.isNotBlank(gpProductionFlow.getProductName())) {
            GpLossRate gpLossRate = iGpLossRateService.getOne(new LambdaQueryWrapper<GpLossRate>()
                    .eq(GpLossRate::getProductName, gpProductionFlow.getProductName())
                    .eq(GpLossRate::getDelStatus, YesNoEnum.NO.getKey())
                    .last("limit 1"));
            if (gpLossRate != null) {
                gpProductionFlow.setLossRate(gpLossRate.getLossRate());
            }
        }
        // 标准出码率
        if (StringUtils.isNotBlank(gpProductionFlow.getProductName()) && StringUtils.isNotBlank(gpProductionFlow.getColour())) {
            GpOutputRate gpOutputRate = iGpOutputRateService.getOne(new LambdaQueryWrapper<GpOutputRate>()
                    .eq(GpOutputRate::getProductName, gpProductionFlow.getProductName())
                    .eq(GpOutputRate::getColour, gpProductionFlow.getColour())
                    .eq(GpOutputRate::getDelStatus, YesNoEnum.NO.getKey())
                    .last("limit 1"));
            if (gpOutputRate != null) {
                gpProductionFlow.setStandardOutputRate(gpOutputRate.getOutputRate());
            }
        }
        // 损耗=进仓重量-成品净重
        if (gpProductionFlow.getWarehouseEntryWeight() != null && gpProductionFlow.getFinishProductWeight() != null) {
            BigDecimal warehouseEntryWeight = BigDecimal.valueOf(gpProductionFlow.getWarehouseEntryWeight());
            gpProductionFlow.setLossWeight(warehouseEntryWeight.subtract(gpProductionFlow.getFinishProductWeight()));
            // 损耗率=损耗/染厂进仓数量
            gpProductionFlow.setLossRate(gpProductionFlow.getLossWeight().multiply(BigDecimal.valueOf(100)).divide(warehouseEntryWeight, 2, RoundingMode.HALF_UP));
            // 损耗差异=损耗率-正常损耗值
            if (gpProductionFlow.getNormalLossValue() != null) {
                gpProductionFlow.setLossDiff(gpProductionFlow.getLossRate().subtract(gpProductionFlow.getNormalLossValue()));
            }
        }
        if (gpProductionFlow.getFinishProductQuantitySufficient() != null) {
            // 胚布出码率=成品总足码数-胚布进仓数量
            if (gpProductionFlow.getWarehouseEntryWeight() != null) {
                BigDecimal warehouseEntryWeight = BigDecimal.valueOf(gpProductionFlow.getWarehouseEntryWeight());
                gpProductionFlow.setGreyClothOutputRate(gpProductionFlow.getFinishProductQuantitySufficient().subtract(warehouseEntryWeight));
                // 成本=（胚布价+染费价+运费价（默认1元））/胚布出码率
                if (gpProductionFlow.getGreyClothUnitPrice() != null
                        && gpProductionFlow.getDyeingFeeUnitPrice() != null
                        && gpProductionFlow.getGreyClothOutputRate().compareTo(BigDecimal.ZERO) != 0) {
                    gpProductionFlow.setCost((gpProductionFlow.getGreyClothUnitPrice().add(gpProductionFlow.getDyeingFeeUnitPrice()).add(BigDecimal.ONE))
                            .multiply(BigDecimal.valueOf(100))
                            .divide(gpProductionFlow.getGreyClothOutputRate(), 2, RoundingMode.HALF_UP));
                }
            }
            // 成品出码率=成品总足码数-成品净重数
            if (gpProductionFlow.getFinishProductWeight() != null) {
                gpProductionFlow.setFinishProductOutputRate(gpProductionFlow.getFinishProductQuantitySufficient().subtract(gpProductionFlow.getFinishProductWeight()));
                // 出码差异=成品出码率-标准出码率
                if (gpProductionFlow.getStandardOutputRate() != null) {
                    gpProductionFlow.setOutputDiff(gpProductionFlow.getFinishProductOutputRate().subtract(gpProductionFlow.getStandardOutputRate()));
                }
            }
        }
        gpProductionFlow.setSizeBar(gpProductionFlow.getSizeBar());
        try {
            // 成品总码数（足） = IF(大小条>0,(成品条数-1)*打卷规格足+大小条,成品条数*打卷规格足)
            if (gpProductionFlow.getCodingSpecificationsSufficient() != null && gpProductionFlow.getQuantity() != null) {
                if (gpProductionFlow.getSizeBar() != null && gpProductionFlow.getSizeBar() > 0) {
                    // (成品条数-1)*打卷规格足+大小条
                    gpProductionFlow.setFinishProductQuantitySufficient(BigDecimal.valueOf(gpProductionFlow.getQuantity() - 1).multiply(new BigDecimal(gpProductionFlow.getCodingSpecificationsSufficient())).add(BigDecimal.valueOf(gpProductionFlow.getSizeBar())));
                } else {
                    // 成品条数*打卷规格足
                    gpProductionFlow.setFinishProductQuantitySufficient(BigDecimal.valueOf(gpProductionFlow.getQuantity()).multiply(new BigDecimal(gpProductionFlow.getCodingSpecificationsSufficient())));
                }
            }
        } catch (NumberFormatException e) {
        }
        try {
            // 成品总码数（空） = IF(大小条>0,(成品条数-1)*打卷规格空+大小条,成品条数*打卷规格空)
            if (gpProductionFlow.getCodingSpecificationsEmpty() != null && gpProductionFlow.getQuantity() != null) {
                if (gpProductionFlow.getSizeBar() != null && gpProductionFlow.getSizeBar() > 0) {
                    // (成品条数-1)*打卷规格空+大小条
                    gpProductionFlow.setFinishProductQuantityEmpty(BigDecimal.valueOf(gpProductionFlow.getQuantity() - 1).multiply(new BigDecimal(gpProductionFlow.getCodingSpecificationsEmpty())).add(BigDecimal.valueOf(gpProductionFlow.getSizeBar())));
                } else {
                    // 成品条数*打卷规格空
                    gpProductionFlow.setFinishProductQuantityEmpty(BigDecimal.valueOf(gpProductionFlow.getQuantity()).multiply(new BigDecimal(gpProductionFlow.getCodingSpecificationsEmpty())));
                }
            }
        } catch (NumberFormatException e) {
        }
    }
}
